//web 是一个轻量级的Go Web开发框架.它的目目的是提供一个简单 高效的web服务
package web

import (
	"crypto/tls"
	"golang.org/x/net/websocket"
	"log"
	"mime"
	"net/http"
	"os"
	"path"
	"reflect"
	"strings"
)

//上下文  每次请求都创建一个上下文对象。每个handle都要携带这个Context，并且要作为第一个传递的参数
//它提供了请求和请求对象以及参数信息 和操作Response的方法
type Context struct {
	Request *http.Request
	Params  map[string]string
	Server  *Server
	http.ResponseWriter
}

//向Response里面写入字符串
func (ctx *Context) WriteString(content string) {
	ctx.ResponseWriter.Write([]byte(content))
}

//Abort是一个帮助方法 用来发送4XX 5XX拒绝请求的 HTTP Header
//一旦这个函数调用了，如何来自Hander的写入数据都不会输出。
func (ctx *Context) Abort(status int, body string) {
	ctx.SetHeader("Content-Type", "text/html; charset=utf-8", true)
	ctx.ResponseWriter.WriteHeader(status)
	ctx.ResponseWriter.Write([]byte(body))
}

//Redirect 3xx重定向
func (ctx *Context) Redirect(status int, url_ string) {
	ctx.ResponseWriter.Header().Set("Location", url_)
	ctx.ResponseWriter.WriteHeader(status)
	ctx.ResponseWriter.Write([]byte("Redirecting to: " + url_))
}

//BadRequest  400错误
func (ctx *Context) BadRequest() {
	ctx.ResponseWriter.WriteHeader(400)
}

//写入304Notmodified  头
func (ctx *Context) NotModified() {
	ctx.ResponseWriter.WriteHeader(304)
}

//Unauthorized 401未授权
func (ctx *Context) Unauthorized() {
	ctx.ResponseWriter.WriteHeader(401)
}

//403 禁止访问
func (ctx *Context) Forbidden() {
	ctx.ResponseWriter.WriteHeader(403)
}

// 404 NotFound
func (ctx *Context) NotFound(message string) {
	ctx.ResponseWriter.WriteHeader(404)
	ctx.ResponseWriter.Write([]byte(message))
}

//设置HTTP 文档响应格式  比如输入：ctx.ContentType("json" ) 则设置
// "application/json"
// 如果传入的参数包含是  "/" 则相当于是完全设置头
// 该函数 在没有找到对应的文档格式的时候返回空字符串
// 否则返回对应的文档响应头格式，
func (ctx *Context) ContentType(val string) string {
	var ctype string
	if strings.ContainsRune(val, '/') {
		ctype = val
	} else {
		if !strings.HasPrefix(val, ".") {
			val = "." + val
		}
		ctype = mime.TypeByExtension(val)
	}
	if ctype != "" {
		ctx.Header().Set("Content-Type", ctype)
	}
	return ctype
}

//设置响应头
//如果 unique =true 则数据会相互覆盖 否则会追加
func (ctx *Context) SetHeader(hdr string, val string, unique bool) {
	if unique {
		ctx.Header().Set(hdr, val)
	} else {
		ctx.Header().Add(hdr, val)
	}
}


//将cookie头加入 Response
func (ctx *Context) SetCookie(cookie *http.Cookie) {
	ctx.SetHeader("Set-Cookie", cookie.String(), false)
}

// small optimization: cache the context type instead of repeteadly calling reflect.Typeof
var contextType reflect.Type

var defaultStaticDirs []string

func init() {
	contextType = reflect.TypeOf(Context{})
	//find the location of the exe file
	wd, _ := os.Getwd()
	arg0 := path.Clean(os.Args[0])
	var exeFile string
	if strings.HasPrefix(arg0, "/") {
		exeFile = arg0
	} else {
		//TODO for robustness, search each directory in $PATH
		exeFile = path.Join(wd, arg0)
	}
	parent, _ := path.Split(exeFile)
	defaultStaticDirs = append(defaultStaticDirs, path.Join(parent, "static"))
	defaultStaticDirs = append(defaultStaticDirs, path.Join(wd, "static"))
	return
}

//process 提供了主要的  路由系统
func Process(c http.ResponseWriter, req *http.Request) {
	mainServer.Process(c, req)
}


//开启一个web  application
func Run(addr string) {
	mainServer.Run(addr)
}

// RunTLS 开启一个https的 服务
func RunTLS(addr string, config *tls.Config) {
	mainServer.RunTLS(addr, config)
}

// RunScgi starts the web application and serves SCGI requests for the main server.
func RunScgi(addr string) {
	mainServer.RunScgi(addr)
}

// RunFcgi starts the web application and serves FastCGI requests for the main server.
func RunFcgi(addr string) {
	mainServer.RunFcgi(addr)
}

// Close stops the main server.
func Close() {
	mainServer.Close()
}

// Get adds a handler for the 'GET' http method in the main server.
func Get(route string, handler interface{}) {
	//fmt.Println("xx")
	//mainServer.Get(route, handler)
	mainServer.addRoute(route, "GET", handler)
}

// Post adds a handler for the 'POST' http method in the main server.
func Post(route string, handler interface{}) {
	mainServer.addRoute(route, "POST", handler)
}

// Put adds a handler for the 'PUT' http method in the main server.
func Put(route string, handler interface{}) {
	mainServer.addRoute(route, "PUT", handler)
}

// Delete adds a handler for the 'DELETE' http method in the main server.
func Delete(route string, handler interface{}) {
	mainServer.addRoute(route, "DELETE", handler)
}

// Match adds a handler for an arbitrary http method in the main server.
func Match(method string, route string, handler interface{}) {
	mainServer.addRoute(route, method, handler)
}

// Add a custom http.Handler. Will have no effect when running as FCGI or SCGI.
func Handle(route string, method string, httpHandler http.Handler) {
	mainServer.Handle(route, method, httpHandler)
}


//添加webSockets 处理器 仅仅用在webserver 模式 在FCGI 和SCIG下不起作用
func Websocket(route string, httpHandler websocket.Handler) {
	mainServer.Websocket(route, httpHandler)
}


//设置日志 处理器
func SetLogger(logger *log.Logger) {
	mainServer.Logger = logger
}

//定义一个server的 配置结构体对象
var Config = &ServerConfig{
	RecoverPanic: true,
	ColorOutput:  true,
}

var mainServer = NewServer()
